#include "can_task.h"
#include "DB0.h"
#include "can.h"
#include "global.h"
#include "main.h"
#include "stm32f4xx_hal_cortex.h"
#include "sys.h"
#include "sysconf.h"
#include "usertempconf.h"
#include "db_raw_access.h"
#include <string.h>


CANREC    CanRec;
CANTRN    CanTrn;
CANUPLODE CanUplode;

// 校验参数
u16 CRC16_OUT_RX = 0;
u16 CRC16_OUT_TX = 0;
u8  CRC16_L_RX   = 0;
u8  CRC16_H_RX   = 0;
u8  CRC16_L_TX   = 0;
u8  CRC16_H_TX   = 0;
u16 RegAddr, RegNum; // 起始寄存器、寄存器数目
u16 gAi, gAj, gAk;

static const u8 auchCRCHi[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
    0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00,
    0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80,
    0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
    0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};

static const u8 auchCRCLo[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D,
    0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB,
    0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2,
    0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37,
    0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8,
    0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24,
    0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63,
    0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE,
    0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F,
    0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C,
    0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
    0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46,
    0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40};

/**
 * @brief 读处理
 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
 * ---- ---- --------- --------- ---------
 * fcode type  dbnum   star_addr  readnum
 *
 */
void CAN_sh_protocol_read_handle_v1(void) {
  uint8_t yushu = 0;
  u8      pack; // 包数
  uint8_t status = 0;
  // 先判断是否为8字节数据，不是则直接跳过
  if(CanRec.DataLen != 8)
    return;
  uint8_t  area       = CanRec.TSH_Buff[1];                             // 读取区域
  uint16_t db_num     = (CanRec.TSH_Buff[2] << 8) + CanRec.TSH_Buff[3]; // db编号——I,Q,M不用处理
  uint16_t start_addr = (CanRec.TSH_Buff[4] << 8) + CanRec.TSH_Buff[5]; // 开始地址
  uint16_t read_num   = (CanRec.TSH_Buff[6] << 8) + CanRec.TSH_Buff[7]; // 读取长度
  memcpy(CanRec.Buff, CanRec.TSH_Buff, 8);
  DBPointer result = FindDBPointerByNumber(db_num);
  switch(area) {
    case SH_DB: {
      if(result.pointer == NULL)
        status = 4; // 下位机未定义数据块

      if(start_addr + read_num + 1 > result.size)
        status = 1; // 地址越界

      // 不存在错误才读数据
      if(status == 0) {
        result.PackDBCall(s7_buffer,S7_BUFFER_SIZE);
        memcpy(CanRec.Buff + 8, s7_buffer + start_addr, read_num);
      }
    } break;
    // 以下3类不考虑db_number
    case SH_IN: {
      if(start_addr + read_num > (DIQM_NUM_LEN + AI_NUM_LEN))
        status = 1; // 地址越界
      if(status == 0) {
        IN_pack_to_buffer();
        memcpy(CanRec.Buff + 8, s7_buffer + start_addr, read_num);
      }
    } break;
    case SH_OUT: {
      if(start_addr + read_num > DIQM_NUM_LEN)
        status = 1; // 地址越界
      if(status == 0) {
        OUT_pack_to_buffer();
        memcpy(CanRec.Buff + 8, s7_buffer + start_addr, read_num);
      }
    } break;
    case SH_MEM: {
      if(start_addr + read_num > DIQM_NUM_LEN)
        status = 1; // 地址越界
      if(status == 0) {
        MEM_pack_to_buffer();
        memcpy(CanRec.Buff + 8, s7_buffer + start_addr, read_num);
      }
    } break;
    default:
      // todo 错误处理
      {
        status = 2; // 区域无效
      }
      break;
  }
  // 发送数据--均发多帧，头帧一样
  uint8_t  last[8] = {0x30, 0x00, 0x00, 0x00, 0x00, status & 0xFF, 0x00, 0x00}; // 尾帧
  uint16_t sendlen = 0;
  if(status == 0) {
    sendlen = read_num + 16;
    memcpy(CanRec.Buff + read_num + 8, last, 6);
  } else {
    sendlen = 16;
    memcpy(CanRec.Buff + 8, last, 6);
  }
  yushu = sendlen % 8;
  if(yushu != 0)
    pack = sendlen / 8 + 1;
  else
    pack = sendlen / 8;

  // 校验
  CRC16_OUT_TX             = CRC16(CanRec.Buff, sendlen - 2);
  CanRec.Buff[sendlen - 2] = (CRC16_OUT_TX >> 8) & 0xFF;
  CanRec.Buff[sendlen - 1] = (CRC16_OUT_TX) & 0xFF;
  HAL_NVIC_DisableIRQ(CAN_RX0_IRQn);

  // 数据帧
  for(uint8_t i = 0; i < pack; i++) {
    if(i == pack - 1 && yushu != 0) {
      can_send_msg(SysPara.g_usAddr + CanRec.StdID, CanRec.Buff + i * 8, yushu);
    } else {
      can_send_msg(SysPara.g_usAddr + CanRec.StdID, CanRec.Buff + i * 8, 8);
    }
  }

  HAL_NVIC_EnableIRQ(CAN_RX0_IRQn);
}
/**
 * 收->帧结构两帧：12字节
 * 0x31 0x01 0x00 0x00 0x00 0x00 0x00 0x00 | 0x00 0x00 0x00 0x00
 * ---- ---- --------- -------------- ----   -------------------
 * fcode|type| dbnum  |    offset    |w_type| value
 *
 * 发->帧结构一帧：8字节
 * 0x31 0x01 0x00 0x00 0x00 0x00 0x00 0x00
 * ---- ---- --------- -------------- ----
 * fcode|type| dbnum  |    offset    |status
 */

/**
 * @brief 处理具体的写操作 - 按照正确流程实现
 * @param area 区域类型
 * @param w_type 写入数据类型
 * @param byte_offset 字节偏移
 * @param bit_offset 位偏移
 * @return 状态码 0:成功, 9:写失败
 */
static uint8_t
process_write_operation(uint8_t area, uint8_t w_type, uint16_t byte_offset, uint8_t bit_offset, DBPointer* db_ptr) {
  uint8_t status = 0;

  // 1. 先打包确保s7_buffer数据是最新的
  switch(area) {
    case SH_DB:
      db_ptr->PackDBCall(s7_buffer,S7_BUFFER_SIZE);
      break;
    case SH_IN:
      IN_pack_to_buffer();
      break;
    case SH_OUT:
      OUT_pack_to_buffer();
      break;
    case SH_MEM:
      MEM_pack_to_buffer();
      break;
  }

  // 2. 写入新值到s7_buffer
  switch(w_type) {
    case SH_W_BIT: {
      uint8_t value = CanRec.TSH_Buff[11] & 0x01;
      write_bool_be(s7_buffer, S7_BUFFER_SIZE, byte_offset, bit_offset, &value);
      break;
    }
    case SH_W_BYTE: {
      uint8_t value = CanRec.TSH_Buff[11];
      write_u8_be(s7_buffer, S7_BUFFER_SIZE, byte_offset, 0, &value);
      break;
    }
    case SH_W_WORD: {
      uint16_t value = (CanRec.TSH_Buff[10] << 8) | CanRec.TSH_Buff[11];
      write_u16_be(s7_buffer, S7_BUFFER_SIZE, byte_offset, 0, &value);
      break;
    }
    case SH_W_DWORD: {
      uint32_t value =
          (CanRec.TSH_Buff[8] << 24) | (CanRec.TSH_Buff[9] << 16) | (CanRec.TSH_Buff[10] << 8) | CanRec.TSH_Buff[11];
      write_u32_be(s7_buffer, S7_BUFFER_SIZE, byte_offset, 0, &value);
      break;
    }
    default:
      return 2; // 无效写入类型
  }

  // 3. 解包到特定区域数据结构
  switch(area) {
    case SH_DB:
      db_ptr->UnPackDBCall(s7_buffer,S7_BUFFER_SIZE);
      break;
    case SH_IN:
      IN_unpack_from_buffer();
      break;
    case SH_OUT:
      OUT_unpack_from_buffer();
      break;
    case SH_MEM:
      MEM_unpack_from_buffer();
      break;
  }

  // 4. 再次打包确保数据一致性
  switch(area) {
    case SH_DB:
      db_ptr->PackDBCall(s7_buffer,S7_BUFFER_SIZE);
      break;
    case SH_IN:
      IN_pack_to_buffer();
      break;
    case SH_OUT:
      OUT_pack_to_buffer();
      break;
    case SH_MEM:
      MEM_pack_to_buffer();
      break;
  }

  // 5. 从s7_buffer读取验证
  switch(w_type) {
    case SH_W_BIT: {
      uint8_t value = CanRec.TSH_Buff[11] & 0x01;
      uint8_t change;
      read_bool_be(s7_buffer, S7_BUFFER_SIZE, byte_offset, bit_offset, &change);
      if(change != value) {
        status = 9; // 写失败
      }
      break;
    }
    case SH_W_BYTE: {
      uint8_t value = CanRec.TSH_Buff[11];
      uint8_t change;
      read_u8_be(s7_buffer, S7_BUFFER_SIZE, byte_offset, bit_offset, &change);
      if(change != value) {
        status = 9; // 写失败
      }
      break;
    }
    case SH_W_WORD: {
      uint16_t value = (CanRec.TSH_Buff[10] << 8) | CanRec.TSH_Buff[11];
      uint16_t change;
      read_u16_be(s7_buffer, S7_BUFFER_SIZE, byte_offset, bit_offset, &change);
      if(change != value) {
        status = 9; // 写失败
      }
      break;
    }
    case SH_W_DWORD: {
      uint32_t value =
          (CanRec.TSH_Buff[8] << 24) | (CanRec.TSH_Buff[9] << 16) | (CanRec.TSH_Buff[10] << 8) | CanRec.TSH_Buff[11];
      uint32_t change;
      read_u32_be(s7_buffer, S7_BUFFER_SIZE, byte_offset, bit_offset, &change);
      if(change != value) {
        status = 9; // 写失败
      }
      break;
    }
  }

  return status;
}
/**
 * @brief 写处理

 */
void CAN_sh_protocol_write_handle_v1(void) {
  uint8_t status = 0;
  // 先判断是否为12字节数据，不是则直接跳过

  uint8_t  area        = CanRec.TSH_Buff[1];                             // 读取区域
  uint16_t db_num      = (CanRec.TSH_Buff[2] << 8) + CanRec.TSH_Buff[3]; // db编号——I,Q,M不用处理
  uint32_t offset      = (CanRec.TSH_Buff[4] << 16) + (CanRec.TSH_Buff[5] << 8) + CanRec.TSH_Buff[6];
  uint16_t byte_offset = (offset >> 3) & 0xFFFF; // 字偏移
  uint8_t  bit_offset  = offset & 0x07;          // 位偏移
  uint8_t  w_type      = CanRec.TSH_Buff[7];
  memcpy(CanRec.Buff, CanRec.TSH_Buff, 7); // 拷贝前7个字节
  DBPointer result = FindDBPointerByNumber(db_num);
  switch(area) {
    case SH_DB: {
      if(result.pointer == NULL)
        status = 4; // db越界
      else if(byte_offset + 1 > result.size)
        status = 1; // 地址越界
      else {
        // 直接调用处理函数，不再需要额外的打包操作
        status = process_write_operation(SH_DB, w_type, byte_offset, bit_offset, &result);
      }
      CanRec.Buff[7] = status;
      can_send_msg(SysPara.g_usAddr + CanRec.StdID, CanRec.Buff, 8);
    } break;

    case SH_IN: {
      if(byte_offset > (DIQM_NUM_LEN + AI_NUM_LEN))
        status = 1; // 地址越界
      else {
        // 所有操作都在process_write_operation中完成
        status = process_write_operation(SH_IN, w_type, byte_offset, bit_offset, &result);
      }
      CanRec.Buff[7] = status;
      can_send_msg(SysPara.g_usAddr + CanRec.StdID, CanRec.Buff, 8);
    } break;

    case SH_OUT: {
      if(byte_offset > DIQM_NUM_LEN)
        status = 1; // 地址越界
      else {
        // 所有操作都在process_write_operation中完成
        status = process_write_operation(SH_OUT, w_type, byte_offset, bit_offset, &result);
      }
      CanRec.Buff[7] = status;
      can_send_msg(SysPara.g_usAddr + CanRec.StdID, CanRec.Buff, 8);
    } break;

    case SH_MEM: {
      if(byte_offset > DIQM_NUM_LEN)
        status = 1; // 地址越界
      else {
        // 所有操作都在process_write_operation中完成
        status = process_write_operation(SH_MEM, w_type, byte_offset, bit_offset, &result);
      }
      CanRec.Buff[7] = status;
      can_send_msg(SysPara.g_usAddr + CanRec.StdID, CanRec.Buff, 8);
    } break;

    default: {
      status         = 2; // 区域无效
      CanRec.Buff[7] = status;
      can_send_msg(SysPara.g_usAddr + CanRec.StdID, CanRec.Buff, 8);
    } break;
  }
}
/**
 * @brief 自定义协议解析应答函数
 *
 */
void CAN_SH_PROTOCOL_V1(void) {
  CanRec.OverTimeCount = CanTimeOut; // 注意放在判断帧ID后面
  CanRec.OverTimeFlag  = RESET;
  CanRec.Addr          = CanRec.StdID;       // 帧ID
  CanRec.FuncCode      = CanRec.TSH_Buff[0]; // 功能码
  if(CanRec.Addr > TSH_Address_Max)
    return;
  switch(CanRec.FuncCode) {
    case SH_PROTOCOL_READ_FUNC_CODE: {
      CAN_sh_protocol_read_handle_v1();
    } break;
    case SH_PROTOCOL_WRITE_FUNC_CODE: {
      CAN_sh_protocol_write_handle_v1();
    } break;
  }
}

/**********************************************************************
 * @FunctionName    void CAN_Module_Data(void)
 * @brief           扩展模块数据映射
 * @param[in]       无
 * @param[out]      无
 * @return          无
 *********************************************************************/
static void WriteBits(u8* src, u8 start, u8 end, Bool (*dst)[8], u8 offset) {
  for(u8 j = start; j < end; j++) {
    u8 data_byte = src[offset + j - start];
    for(u8 bit = 0; bit < 8; bit++) {
      dst[j][bit] = (data_byte >> bit) & 0x01;
    }
  }
}

void CAN_Module_Data(void) {
  CanRec.OverTimeCount = CanTimeOut; // 注意放在判断帧ID后面
  CanRec.OverTimeFlag  = RESET;
  u8 address           = CanRec.Buff[0];
  u8 function_code     = CanRec.Buff[1];
  u8 data_byte_count   = CanRec.Buff[2];

  for(u8 i = 0; i < MODULE_MAX; i++) {
    if((address == configuration_Sys[i].Address_CAN) && configuration_Sys[i].Enable) {
      configuration_Sys[i].Sign           = 1;
      configuration_Sys[i].TimeOutCounter = CAN_TIME_OUT_MS;

      if((address >= DI8_Address_Min) && (address <= DI8_Address_Max)) {
        u8 start = configuration_Sys[i].Address_DIorAI;
        WriteBits(CanRec.Buff, start, start + data_byte_count, g_DB0_t->I, 3);
      } else if((address >= DI16_Address_Min) && (address <= DI16_Address_Max)) {
        u8 start = configuration_Sys[i].Address_DIorAI;
        WriteBits(CanRec.Buff, start, start + data_byte_count, g_DB0_t->I, 3);
      } else if((address >= DO8_Address_Min) && (address <= DO8_Address_Max)) {
        u8 start = configuration_Sys[i].Address_DO;
        WriteBits(CanRec.Buff, start, start + data_byte_count, g_DB0_t->Q, 3);
      } else if((address >= DO16_Address_Min) && (address <= DO16_Address_Max)) {
        u8 start = configuration_Sys[i].Address_DO;
        WriteBits(CanRec.Buff, start, start + data_byte_count, g_DB0_t->Q, 3);
      } else if((address >= DIO16_Address_Min) && (address <= DIO16_Address_Max)) {
        if(function_code == 0x04) {
          // 输入状态
          u8 start_DI = configuration_Sys[i].Address_DIorAI;
          WriteBits(CanRec.Buff, start_DI, start_DI + 2, g_DB0_t->I, 2);

          // 输出状态
          u8 start_DO = configuration_Sys[i].Address_DO;
          WriteBits(CanRec.Buff, start_DO, start_DO + 2, g_DB0_t->Q, 4);
        }
      }
    }
  }
}
/**********************************************************************
 * @FunctionName	void CAN_AI_Data(void)
 * @brief				  扩展模块数据存储
 * @param[in]					无
 * @param[out]				无
 * @return						无
 *********************************************************************/
void CAN_AI_Data(void) {
  CanRec.OverTimeCount = CanTimeOut; // 注意放在判断帧ID后面
  CanRec.OverTimeFlag  = RESET;
  u8 address_AI        = CanRec.AI_Buff[0];
  u8 Start_Group_AI;

  // 判断所属模块
  if((address_AI >= 70) && (address_AI <= 79)) // 判断4RTD
  {
    for(u8 i = 0; i < MODULE_MAX; i++) // 组态都遍历一遍 没别的办法
    {
      if((address_AI == configuration_Sys[i].Address_CAN) && configuration_Sys[i].Enable) // 判断收到的符合组态地址
      {
        configuration_Sys[i].Sign           = 1;
        configuration_Sys[i].TimeOutCounter = CAN_TIME_OUT_MS;
        Start_Group_AI                      = configuration_Sys[i].Address_DIorAI; // 取出组态变量地址

        for(u8 byte = 0; byte < 4; byte++) {
          uint16_t temperature               = (CanRec.AI_Buff[3 + 2 * byte] << 8) | CanRec.AI_Buff[4 + 2 * byte];
          g_DB0_t->AI[Start_Group_AI + byte] = temperature;
        }
      }
    }
  } else if((address_AI >= 80) && (address_AI <= 89)) // 判断AI4 13Bit
  {
    for(u8 i = 0; i < MODULE_MAX; i++) // 组态都遍历一遍 没别的办法
    {
      if((address_AI == configuration_Sys[i].Address_CAN) && configuration_Sys[i].Enable) // 判断收到的符合组态地址
      {
        configuration_Sys[i].Sign           = 1;
        configuration_Sys[i].TimeOutCounter = CAN_TIME_OUT_MS;
        Start_Group_AI                      = configuration_Sys[i].Address_DIorAI; // 取出组态变量地址

        for(u8 byte = 0; byte < 4; byte++) {
          uint16_t temperature               = (CanRec.AI_Buff[3 + 2 * byte] << 8) | CanRec.AI_Buff[4 + 2 * byte];
          g_DB0_t->AI[Start_Group_AI + byte] = temperature;
        }
      }
    }
  } else if((address_AI >= 90) && (address_AI <= 99)) // 判断AI8 13Bit
  {
    for(u8 i = 0; i < MODULE_MAX; i++) // 组态都遍历一遍 没别的办法
    {
      if((address_AI == configuration_Sys[i].Address_CAN) && configuration_Sys[i].Enable) // 判断收到的符合组态地址
      {
        configuration_Sys[i].Sign           = 1;
        configuration_Sys[i].TimeOutCounter = CAN_TIME_OUT_MS;
        Start_Group_AI                      = configuration_Sys[i].Address_DIorAI; // 取出组态变量地址

        for(u8 byte = 0; byte < 8; byte++) {
          uint16_t temperature               = (CanRec.AI_Buff[3 + 2 * byte] << 8) | CanRec.AI_Buff[4 + 2 * byte];
          g_DB0_t->AI[Start_Group_AI + byte] = temperature;
        }
      }
    }
  }
}
/**********************************************************************
 * @FunctionName	ClearDataBuff(void)
 * @brief				  清除数组任务
 * @param[in]					无
 * @param[out]				无
 * @return						无
 *********************************************************************/
void ClearDataBuff(void) // 清理发送 接收缓存BUFF
{
  memset(&CanRec.Buff, 0x00, sizeof(CanRec.Buff));
  memset(&CanRec.TSH_Buff, 0x00, sizeof(CanRec.TSH_Buff));
  memset(&CanRec.AI_Buff, 0x00, sizeof(CanRec.AI_Buff));
  memset(&CanTrn.Buff, 0x00, sizeof(CanTrn.Buff));
}

/**********************************************************************
 * @FunctionName	u16 CRC16(u8 *_pBuf, u16 _usLen)
 * @brief				  CRC校验、检查
 * @param[in]					无
 * @param[out]				无
 * @return						无
 *********************************************************************/
u8 CanRecCRC(u16 rd, u8 usDataLen) {
  u8 uchCRCHi = 0xFF; // high byte of CRC initialized
  u8 uchCRCLo = 0xFF; // low byte of CRC initialized
  u8 uIndex;          // will index into CRC lookup table
  while(usDataLen--)  // pass through message buffer
  {
    uIndex   = uchCRCHi ^ CanRec.Buff[rd]; // calculate the CRC
    rd       = (rd + 1) & CAN_REC_LEN;
    uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
    uchCRCLo = auchCRCLo[uIndex];
  }
  if(uchCRCHi == CanRec.Buff[rd]) {
    rd = (rd + 1) & CAN_REC_LEN;
    if(uchCRCLo == CanRec.Buff[rd])
      return 0; // crc OK
  }
  return 1; // crc err
}

u8 CanRecCRC_TSH(u16 rd, u8 usDataLen) {
  u8 uchCRCHi = 0xFF; // high byte of CRC initialized
  u8 uchCRCLo = 0xFF; // low byte of CRC initialized
  u8 uIndex;          // will index into CRC lookup table
  while(usDataLen--)  // pass through message buffer
  {
    uIndex   = uchCRCHi ^ CanRec.TSH_Buff[rd]; // calculate the CRC
    rd       = (rd + 1) & CAN_REC_LEN;
    uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
    uchCRCLo = auchCRCLo[uIndex];
  }
  if(uchCRCHi == CanRec.TSH_Buff[rd]) {
    rd = (rd + 1) & CAN_REC_LEN;
    if(uchCRCLo == CanRec.TSH_Buff[rd])
      return 0; // crc OK
  }
  return 1; // crc err
}

u8 CanRecCRC_AI(u16 rd, u8 usDataLen) {
  u8 uchCRCHi = 0xFF; // high byte of CRC initialized
  u8 uchCRCLo = 0xFF; // low byte of CRC initialized
  u8 uIndex;          // will index into CRC lookup table
  while(usDataLen--)  // pass through message buffer
  {
    uIndex   = uchCRCHi ^ CanRec.AI_Buff[rd]; // calculate the CRC
    rd       = (rd + 1) & CAN_REC_LEN;
    uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
    uchCRCLo = auchCRCLo[uIndex];
  }
  if(uchCRCHi == CanRec.AI_Buff[rd]) {
    rd = (rd + 1) & CAN_REC_LEN;
    if(uchCRCLo == CanRec.AI_Buff[rd])
      return 0; // crc OK
  }
  return 1; // crc err
}

u16 msrCRC(char* pcMess, u8 wLen) {
  u16 sum_crc;
  u8  cHi, cLo; //	CRC Acc (MSB & LSB)
  u8  w;        //	CRC Shift In Index
  cHi = 0xFF;   //	Init CRC
  cLo = 0xFF;
  while(wLen--) {             //	For Each Byte
    w   = cHi ^ (*pcMess++);  //	Next Table Index
    cHi = cLo ^ auchCRCHi[w]; //	Next CRC
    cLo = auchCRCLo[w];
  }
  sum_crc = cLo;
  sum_crc = (sum_crc << 8) | cHi;
  return (u16) sum_crc; //	Return Composite
}

u16 CRC16(u8* _pBuf, u16 _usLen) {
  u8  ucCRCHi = 0xFF; /* 高CRC字节初始化 */
  u8  ucCRCLo = 0xFF; /* 低CRC 字节初始化 */
  u16 usIndex;        /* CRC循环中的索引 */

  while(_usLen--) {
    usIndex = ucCRCHi ^ *_pBuf++; /* 计算CRC */
    ucCRCHi = ucCRCLo ^ auchCRCHi[usIndex];
    ucCRCLo = auchCRCLo[usIndex];
  }
  return ((u16) ucCRCHi << 8 | ucCRCLo);
}

/**********************************************************************
 * @FunctionName	CAN_RX_Communication(void)
 * @brief				  CAN实时应答任务
 * @param[in]					无
 * @param[out]				无
 * @return						无
 *********************************************************************/
void CAN_RX_Communication(void) {

  static u8 isAI        = 0;
  static u8 isTSH       = 0;
  static u8 checkLen    = 0;
  static u8 ModuleStype = 0;

  if((CanRec.State == SET) || (CanRec.AI_State == SET) || (CanRec.TSH_State == SET)) {
    if(CanRec.StdID <= TSH_Address_Max) {
      ModuleStype = 1;
      isTSH       = 1;
    } else if((CanRec.StdID > TSH_Address_Max) && (CanRec.StdID <= DIO16_Address_Max)) {
      ModuleStype = 2;
    } else if((CanRec.StdID > DIO16_Address_Max) && (CanRec.StdID <= AI8_13BIT_Address_Max)) {
      ModuleStype = 3;
      isAI        = 1;
    } else {
      ModuleStype = 0;
      ClearDataBuff(); // 消除无效数据
      if(isAI)
        CanRec.AI_State = RESET;
      else if(isTSH)
        CanRec.TSH_State = RESET;
      else
        CanRec.State = RESET;
      return;
    }
    switch(ModuleStype) {
      case 1:
        CAN_SH_PROTOCOL_V1();
        break;
      case 2:
        checkLen = CanRec.DataLen - 2;
        if(CanRecCRC(0, checkLen)) // 模块 CRC 校验不同
        {
          ClearDataBuff(); // 消除无效数据
          CanRec.State = RESET;
          return;
        }
        CAN_Module_Data();
        break;
      case 3:
        if(CanRec.StdID >= AI4_RTD_Address_Min && CanRec.StdID <= AI4_13BIT_Address_Max) {
          checkLen = 11;
        } else if(CanRec.StdID >= AI8_13BIT_Address_Min && CanRec.StdID <= AI8_13BIT_Address_Max) {
          checkLen = 19;
        }
        if(CanRecCRC_AI(0, checkLen)) // 模拟模块 CRC 校验不同
        {
          ClearDataBuff(); // 消除无效数据
          CanRec.AI_State = RESET;
          isAI            = 0;
          return;
        }
        CAN_AI_Data();
        break;
      default:
        break;
    }
    ClearDataBuff(); // 消除无效数据
    if(isAI)
      CanRec.AI_State = RESET;
    else if(isTSH)
      CanRec.TSH_State = RESET;
    else
      CanRec.State = RESET;
  }
}

/**********************************************************************
 * @FunctionName	void Rec_TimeOut_Chk(void)
 * @brief				  超时函数
 * @param[in]					无
 * @param[out]				无
 * @return						无
 *********************************************************************/
void Rec_TimeOut_Chk(void) {
  if(CanRec.OverTimeCount != 0) {
    if(--CanRec.OverTimeCount == 0) {
      CanRec.OverTimeFlag = SET;
    }
  } else {
    CanRec.OverTimeFlag = SET;
  }
}

/*
*********************************************************************************************************
*	函 数 名: MODH_SendAckWithCRC
*	功能说明: 发送应答,自动加CRC.
*	形    参: 无。发送数据在CanTrn.Buff[], CanTrn.TxCount
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_SendAckWithCRC(void) {
  uint16_t crc;

  crc                           = CRC16(CanTrn.Buff, CanTrn.TxCount);
  CanTrn.Buff[CanTrn.TxCount++] = crc >> 8;
  CanTrn.Buff[CanTrn.TxCount++] = crc;
  can_send_msg(SysPara.g_usAddr, CanTrn.Buff, CanTrn.TxCount);
}

void MODH_SendAckWithCRC1(void) {
  uint16_t crc;

  crc                           = CRC16(CanTrn.Buff, CanTrn.TxCount);
  CanTrn.Buff[CanTrn.TxCount++] = crc >> 8;
  CanTrn.Buff[CanTrn.TxCount++] = crc;
  can_send_msg(0x100, CanTrn.Buff, CanTrn.TxCount);
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send05H
*	功能说明: 发送05H指令，写强置单线圈
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _value : 寄存器值,2字节
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Send05H(uint8_t _addr, uint16_t _reg, uint16_t _value) {
  //	__disable_irq();  // 进入临界区

  CanTrn.TxCount                = 0;
  CanTrn.Buff[CanTrn.TxCount++] = _addr;                /* 从站地址 */
  CanTrn.Buff[CanTrn.TxCount++] = FUNC_SET_DO;          /* 功能码 */
  CanTrn.Buff[CanTrn.TxCount++] = _reg >> 8;            /* 寄存器编号 高字节 */
  CanTrn.Buff[CanTrn.TxCount++] = _reg;                 /* 寄存器编号 低字节 */
  CanTrn.Buff[CanTrn.TxCount++] = (u8) (_value & 0xFF); /* 寄存器值 低字节 */
  CanTrn.Buff[CanTrn.TxCount++] = (u8) (_value >> 8);   /* 寄存器值 高字节 */

  MODH_SendAckWithCRC(); /* 发送数据，自动加CRC */
  // __enable_irq();   // 退出临界区
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send05H
*	功能说明: 发送05H指令，写强置单线圈
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _value : 寄存器值,2字节
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Send06H(uint8_t _value) {
  CanTrn.TxCount                = 0;
  CanTrn.Buff[CanTrn.TxCount++] = 0xFF;            /* 从站地址 */
  CanTrn.Buff[CanTrn.TxCount++] = FUNC_SET_SINGLE; /* 功能码 */
  CanTrn.Buff[CanTrn.TxCount++] = 0x00;            /* 寄存器编号 高字节 */
  CanTrn.Buff[CanTrn.TxCount++] = 0x00;            /* 寄存器编号 低字节 */
  CanTrn.Buff[CanTrn.TxCount++] = 0x00;            /* 寄存器值 高字节 */
  CanTrn.Buff[CanTrn.TxCount++] = _value;          /* 寄存器值 低字节 */

  MODH_SendAckWithCRC(); /* 发送数据，自动加CRC */
}

/**********************************************************************
 * @FunctionName		Can_Uplode(void)
 * @brief						CAN定时上传
 * @param[in]
 * @param[out]
 * @return
 *********************************************************************/
void Can_Uplode(void) // 本机信息定时主动上传
{
  CanTrn.TxCount                = 0;
  CanTrn.Buff[CanTrn.TxCount++] = 0XFF;
  CanTrn.Buff[CanTrn.TxCount++] = FUNC_READ_HOLD;
  CanTrn.Buff[CanTrn.TxCount++] = 0xFF;
  CanTrn.Buff[CanTrn.TxCount++] = 0xFF;
  CanTrn.Buff[CanTrn.TxCount++] = 0x00;
  CanTrn.Buff[CanTrn.TxCount++] = 0x00;

  MODH_SendAckWithCRC1(); /* 发送数据，自动加CRC */
}
